package com.shy.base.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;

import jodd.bean.BeanCopy;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gson.Gson;

/**
 * 复制对象类
 * <p>@use Object old=objectBusiness.getObject(obj.getId()); BeanUtil.merge(old,
 *      obj);//后面obj里的不为null的属性付给old 属性 regionService.update(old);</p>
 * 
 * @author shanhanyu
 * @date 2018/1/23下午2:54:32
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class BeanUtil {

    /**
     * 将src中不为null的属性赋值到dest中
     * 
     * @param dest
     *            目标对象
     * @param src
     *            源对象
     * @param <T>
     *            泛型
     * @return
     * @author shanhanyu
     * @date 2018/2/6
     */
    public static <T> T merge(T dest, T src) {

        BeanCopy.beans(src, dest).ignoreNulls(true).copy();
        return dest;
    }

    /**
     * 复制对象
     * 
     * @param dest
     *            目标对象
     * @param src
     *            源对象
     * @author shanhanyu
     * @date 2018/2/6
     */
    public static void copy(Object dest, Object src) {
        BeanCopy.beans(src, dest).copy();
    }

    /**
     * 獲取類的實例化對象
     * 
     * @param clazz
     *            类
     * @param <T>
     *            泛型
     * @return
     * @author shanhanyu
     * @date 2017/11/22下午7:51:20
     */
    public static <T> T newInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 從session中獲取指定的對象
     * 
     * @param session
     *            当前回话session
     * @param key
     *            参数名
     * @param clazz
     *            实际类型
     * @param <T>
     *            泛型
     * @return
     * @author shanhanyu
     * @date 2017/11/22下午7:50:52
     */
    public static <T> T getBean(HttpSession session, String key, Class<T> clazz) {
        ServletContext servletContext = session.getServletContext();
        WebApplicationContext ctx = WebApplicationContextUtils
                .getWebApplicationContext(servletContext);
        return (T) ctx.getBean(key, clazz);
    }

    /**
     * 实体轉map
     * 
     * @param bean
     *            对象
     * @return
     * @author shanhanyu
     * @date 2017/11/22下午7:51:08
     */
    public static Map<String, Object> beanToMap(Object bean) {
        Map<String, Object> map;
        Gson gson = new Gson();
        map = gson.fromJson(gson.toJson(bean), Map.class);
        return map;
    }

    /**
     * 不包括嵌套属性
     * 
     * @param bean
     *            对象
     * @return
     * @throws IntrospectionException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public static Map<String, Object> beanToMap2(Object bean) {
        try {
            Class type = bean.getClass();
            Map returnMap = new HashMap();
            BeanInfo beanInfo = Introspector.getBeanInfo(type);

            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                if (!propertyName.equals("class")) {
                    Method readMethod = descriptor.getReadMethod();
                    Object result = readMethod.invoke(bean, new Object[0]);

                    if (result != null) {
                        if (isBaseType(result.getClass())) {
                            returnMap.put(propertyName, result);
                        }
                    }
                }
            }
            return returnMap;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /** 支持的类型集合 */
    static Set<Class> baseClasses = new HashSet<Class>();

    static {
        baseClasses.add(Byte.class);
        baseClasses.add(Short.class);
        baseClasses.add(Integer.class);
        baseClasses.add(Long.class);
        baseClasses.add(Float.class);
        baseClasses.add(Double.class);
        baseClasses.add(Character.class);
        baseClasses.add(Boolean.class);
        baseClasses.add(String.class);
        baseClasses.add(Date.class);
    }

    /**
     * 类型判断
     * 
     * @param c
     *            当前类型
     * @return
     * @author shanhanyu
     * @date 2018/2/6
     */
    public static boolean isBaseType(Class c) {
        return baseClasses.contains(c);
    }

    /**
     * 嵌套的Bean直接转换成一级属性，如a.b.c，而不是嵌套的Map
     * 
     * @param bean
     *            对象
     * @param name
     *            属性名
     * @return
     */
    public static Map<String, Object> expendBean(Object bean, String name) {

        Map<String, Object> rs = new HashMap<String, Object>();
        if (bean == null) {
            return rs;
        }
        Map<String, Object> map = beanToMap2(bean);
        for (Map.Entry<String, Object> entity : map.entrySet()) {
            rs.put(name + "." + entity.getKey(), entity.getValue());
        }
        return rs;
    }

    /**
     * 获取对象属性
     * 
     * @param obj
     *            对象
     * @param prop
     *            属性
     * @return
     * @author shanhanyu
     * @date 2018/2/6
     */
    public static Object getProp(Object obj, String prop) {
        jodd.bean.BeanUtilBean bb = new jodd.bean.BeanUtilBean();
        return bb.getProperty(obj, prop);
    }

    /**
     * map转换为对象
     * 
     * @param map
     *            当前map
     * @param bean
     *            目标实体
     * @author shanhanyu
     * @date 2018/2/6
     */
    public static void mapToBean(Map map, Object bean) {
        BeanCopy.beans(map, bean).copy();
    }

    /**
     * 過濾指定的属性列表
     * 
     * @param map
     *            当前map
     * @param fields
     *            属性列表
     * @author shanhanyu
     * @date 2017/11/22下午7:51:50
     */
    public static void filterFields(Map map, String[] fields) {
        for (int i = 0; i < fields.length; i++) {
            map.remove(fields[i]);
        }
    }

    /**
     * 布爾值轉int
     * 
     * @param v
     *            参数
     * @return
     * @author shanhanyu
     * @date 2017/11/22下午7:52:15
     */
    public static int boolToInt(boolean v) {
        if (v) {
            return 1;
        }
        return 0;
    }
}
